/*
 *  Copyright (C) 2010 Jesus Navalon i Pastor <jnavalon at redhermes dot net>
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * pn_SetFeatures.java
 *
 * Created on 04/11/2010, 16:14:20
 */

package kuasar.plugin.vmcreator.gui.tooltasks.AddHost;

import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import javax.swing.JFileChooser;
import javax.swing.Timer;
import javax.swing.filechooser.FileFilter;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import kuasar.plugin.Intercom.GUI;
import kuasar.plugin.vmcreator.gui.tooltasks.AddHost.devicesFeat.Attributes;
import kuasar.plugin.vmcreator.gui.tooltasks.AddHost.devicesFeat.ModAttributes;

/**
 *
 * @author Jesus Navalon i Pastor <jnavalon at redhermes dot net>
 */
public class pn_SetFeatures extends kuasar.plugin.classMod.AbstractPanel {

    //MEMORY
    public static final int MEGA = 0;
    public static final int GIGA = 1;
    public static final int TERA = 2;
    //MODULES
    public static final int IDE_MODULE = 0;
    public static final int SATA_MODULE = 1;
    public static final int SCSI_MODULE = 2;
    public static final int SAS_MODULE = 3;
    public static final int FLOPPY_MODULE = 4;
    //DEVICES
    public static final int DVD_DEVICE = 0;
    public static final int HDD_DEVICE = 1;
    public static final int FLOPPY_DEVICE = 2;
    //SLOTS
    Object[] module_slots = new Object[5];
    private pn_TB_AddHost toolbar = null;
    private boolean safeMode = false;
    private DefaultTreeModel model;
    private DefaultMutableTreeNode root;
    private int total_Mods = 5;
    private Component panel = null;
    Timer tim_Info = new Timer(5000, new ActionListener() {

        public void actionPerformed(ActionEvent e) {
            lbl_Info.setText("");
            tim_Info.stop();
        }
    });

    /** Creates new form pn_SetFeatures */
    public pn_SetFeatures(pn_TB_AddHost toolbar) {
        this.toolbar = toolbar;
        initSlots();
        initComponents();
        spn_Features.getViewport().setOpaque(false);
        model = new DefaultTreeModel(null);
        tre_Devices.setBackground(new Color(0, 0, 0, 0));
        spn_Devices.getViewport().setOpaque(false);
        tre_Devices.setModel(model);
        tre_Devices.setCellRenderer(new TreeCellModRenderer());
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("isdevice", false);
        Object data[] = {-1, "System", map};
        root = new DefaultMutableTreeNode(data);
        model.setRoot(root);
        tre_Devices.setSelectionRow(0);
        tre_Devices.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        Load();
    }

    private void initSlots() {
        module_slots[IDE_MODULE] = new boolean[4];
        module_slots[SATA_MODULE] = new boolean[30];
        module_slots[SCSI_MODULE] = new boolean[16];
        module_slots[SAS_MODULE] = new boolean[8];
        module_slots[FLOPPY_MODULE] = new boolean[2];

    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        pmn_addModule = new javax.swing.JPopupMenu();
        mni_IDE = new javax.swing.JMenuItem();
        mni_SATA = new javax.swing.JMenuItem();
        mni_SCSI = new javax.swing.JMenuItem();
        mni_SAS = new javax.swing.JMenuItem();
        mni_floppy = new javax.swing.JMenuItem();
        pmn_addDevices = new javax.swing.JPopupMenu();
        mni_addDVD = new javax.swing.JMenuItem();
        mni_addHDD = new javax.swing.JMenuItem();
        btn_Previous = new javax.swing.JButton();
        btn_Next = new javax.swing.JButton();
        btn_Cancel = new javax.swing.JButton();
        lbl_mem = new javax.swing.JLabel();
        txt_mem = new javax.swing.JTextField();
        cmb_unit = new javax.swing.JComboBox();
        lbl_SafeMode = new javax.swing.JLabel();
        lbl_Disks = new javax.swing.JLabel();
        spn_Devices = new javax.swing.JScrollPane();
        tre_Devices = new javax.swing.JTree();
        lbl_addDevice = new javax.swing.JLabel();
        lbl_remDevice = new javax.swing.JLabel();
        lbl_addModule = new javax.swing.JLabel();
        lbl_remModule = new javax.swing.JLabel();
        lbl_Info = new javax.swing.JLabel();
        spn_Features = new javax.swing.JScrollPane();

        mni_IDE.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/ide_add.png"))); // NOI18N
        mni_IDE.setText("Add IDE Module");
        mni_IDE.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mni_IDEActionPerformed(evt);
            }
        });
        pmn_addModule.add(mni_IDE);

        mni_SATA.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/sata_add.png"))); // NOI18N
        mni_SATA.setText("Add SATA Module");
        mni_SATA.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mni_SATAActionPerformed(evt);
            }
        });
        pmn_addModule.add(mni_SATA);

        mni_SCSI.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/scsi_add.png"))); // NOI18N
        mni_SCSI.setText("Add SCSI Module");
        mni_SCSI.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mni_SCSIActionPerformed(evt);
            }
        });
        pmn_addModule.add(mni_SCSI);

        mni_SAS.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/sata_add.png"))); // NOI18N
        mni_SAS.setText("Add SAS Controller");
        mni_SAS.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mni_SASActionPerformed(evt);
            }
        });
        pmn_addModule.add(mni_SAS);

        mni_floppy.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/floppy_add.png"))); // NOI18N
        mni_floppy.setText("Add Floppy Module");
        mni_floppy.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mni_floppyActionPerformed(evt);
            }
        });
        pmn_addModule.add(mni_floppy);

        mni_addDVD.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/cd_device_add.png"))); // NOI18N
        mni_addDVD.setText("Add CD/DVD Device");
        mni_addDVD.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mni_addDVDActionPerformed(evt);
            }
        });
        pmn_addDevices.add(mni_addDVD);

        mni_addHDD.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/hdd_device_add.png"))); // NOI18N
        mni_addHDD.setText("Add Hard Disk");
        mni_addHDD.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mni_addHDDActionPerformed(evt);
            }
        });
        pmn_addDevices.add(mni_addHDD);

        setOpaque(false);

        btn_Previous.setBackground(new java.awt.Color(0, 0, 0));
        btn_Previous.setForeground(new java.awt.Color(204, 204, 204));
        btn_Previous.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/dialog-previous.png"))); // NOI18N
        btn_Previous.setText("Previous");
        btn_Previous.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btn_PreviousActionPerformed(evt);
            }
        });

        btn_Next.setBackground(new java.awt.Color(0, 0, 0));
        btn_Next.setForeground(new java.awt.Color(204, 204, 204));
        btn_Next.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/dialog-next.png"))); // NOI18N
        btn_Next.setText("Next");
        btn_Next.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btn_NextActionPerformed(evt);
            }
        });

        btn_Cancel.setBackground(new java.awt.Color(0, 0, 0));
        btn_Cancel.setForeground(new java.awt.Color(204, 204, 204));
        btn_Cancel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/dialog-cancel.png"))); // NOI18N
        btn_Cancel.setText("Cancel");
        btn_Cancel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btn_CancelActionPerformed(evt);
            }
        });

        lbl_mem.setForeground(new java.awt.Color(204, 204, 204));
        lbl_mem.setText("Memory :");

        txt_mem.setFont(new java.awt.Font("DejaVu Sans", 0, 18));
        txt_mem.setForeground(new java.awt.Color(0, 0, 0));
        txt_mem.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        txt_mem.setText("512");
        txt_mem.setOpaque(false);
        txt_mem.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                txt_memFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                txt_memFocusLost(evt);
            }
        });

        cmb_unit.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Mb", "Gb", "Tb" }));

        lbl_SafeMode.setForeground(new java.awt.Color(204, 204, 204));
        lbl_SafeMode.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/security-medium.png"))); // NOI18N
        lbl_SafeMode.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        lbl_SafeMode.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                lbl_SafeModeMouseReleased(evt);
            }
        });

        lbl_Disks.setForeground(new java.awt.Color(204, 204, 204));
        lbl_Disks.setText("Disks :");

        spn_Devices.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
        spn_Devices.setViewportBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
        spn_Devices.setOpaque(false);

        tre_Devices.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
        javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("root");
        tre_Devices.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1));
        tre_Devices.setOpaque(false);
        tre_Devices.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
            public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
                tre_DevicesValueChanged(evt);
            }
        });
        spn_Devices.setViewportView(tre_Devices);

        lbl_addDevice.setForeground(new java.awt.Color(204, 204, 204));
        lbl_addDevice.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/noGPL/addDevice22.png"))); // NOI18N
        lbl_addDevice.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        lbl_addDevice.setEnabled(false);
        lbl_addDevice.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                lbl_addDeviceMouseClicked(evt);
            }
        });

        lbl_remDevice.setForeground(new java.awt.Color(204, 204, 204));
        lbl_remDevice.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/noGPL/remDevice22.png"))); // NOI18N
        lbl_remDevice.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        lbl_remDevice.setEnabled(false);
        lbl_remDevice.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                lbl_remDeviceMouseClicked(evt);
            }
        });

        lbl_addModule.setForeground(new java.awt.Color(204, 204, 204));
        lbl_addModule.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/noGPL/addModule22.png"))); // NOI18N
        lbl_addModule.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        lbl_addModule.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                lbl_addModuleMouseClicked(evt);
            }
        });

        lbl_remModule.setForeground(new java.awt.Color(204, 204, 204));
        lbl_remModule.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/noGPL/remModule22.png"))); // NOI18N
        lbl_remModule.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        lbl_remModule.setEnabled(false);
        lbl_remModule.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                lbl_remModuleMouseClicked(evt);
            }
        });

        lbl_Info.setForeground(new java.awt.Color(204, 204, 204));
        lbl_Info.setText(" ");

        spn_Features.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
        spn_Features.setViewportBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
        spn_Features.setOpaque(false);
        spn_Features.addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentResized(java.awt.event.ComponentEvent evt) {
                spn_FeaturesComponentResized(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(35, 35, 35)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(lbl_Disks)
                    .addComponent(lbl_mem))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(txt_mem)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(cmb_unit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(spn_Devices, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(lbl_SafeMode)
                    .addComponent(lbl_remModule)
                    .addComponent(lbl_addDevice)
                    .addComponent(lbl_remDevice)
                    .addComponent(lbl_addModule))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(spn_Features, javax.swing.GroupLayout.DEFAULT_SIZE, 193, Short.MAX_VALUE)
                .addGap(25, 25, 25))
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(lbl_Info, javax.swing.GroupLayout.DEFAULT_SIZE, 251, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(btn_Previous)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(btn_Next)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(btn_Cancel)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(31, 31, 31)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(spn_Features, javax.swing.GroupLayout.DEFAULT_SIZE, 222, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addComponent(lbl_SafeMode, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(lbl_mem)
                                .addComponent(txt_mem, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(cmb_unit, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(lbl_addDevice)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(lbl_remDevice)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(lbl_addModule)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(lbl_remModule))
                            .addComponent(spn_Devices, javax.swing.GroupLayout.DEFAULT_SIZE, 189, Short.MAX_VALUE)
                            .addComponent(lbl_Disks))))
                .addGap(39, 39, 39)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(btn_Cancel)
                    .addComponent(btn_Next)
                    .addComponent(btn_Previous)
                    .addComponent(lbl_Info))
                .addContainerGap())
        );
    }// </editor-fold>//GEN-END:initComponents

    // <editor-fold defaultstate="collapsed" desc="Object Events">
    private void btn_PreviousActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_PreviousActionPerformed
        toolbar.previous();
}//GEN-LAST:event_btn_PreviousActionPerformed

    private void btn_NextActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_NextActionPerformed
        save();
        toolbar.next();
}//GEN-LAST:event_btn_NextActionPerformed

    private void btn_CancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_CancelActionPerformed
        toolbar.exit();
}//GEN-LAST:event_btn_CancelActionPerformed

    private void txt_memFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txt_memFocusGained
        txt_mem.selectAll();
    }//GEN-LAST:event_txt_memFocusGained

    private void lbl_SafeModeMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lbl_SafeModeMouseReleased
        safeMode = !safeMode;
        if (safeMode) {
            lbl_SafeMode.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/security-high.png")));
        } else {
            lbl_SafeMode.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/security-medium.png")));
        }
        GUI.updateUI();
    }//GEN-LAST:event_lbl_SafeModeMouseReleased

    private void txt_memFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txt_memFocusLost
        txt_mem.select(0, 0);
    }//GEN-LAST:event_txt_memFocusLost

    private void lbl_addModuleMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lbl_addModuleMouseClicked
        if (!lbl_addModule.isEnabled()) {
            return;
        }
        pmn_addModule.show(lbl_addModule, evt.getX(), evt.getY());
    }//GEN-LAST:event_lbl_addModuleMouseClicked

    private void mni_IDEActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mni_IDEActionPerformed
        addModule(0);
    }//GEN-LAST:event_mni_IDEActionPerformed

    private void mni_SATAActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mni_SATAActionPerformed
        addModule(1);
    }//GEN-LAST:event_mni_SATAActionPerformed

    private void mni_SCSIActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mni_SCSIActionPerformed
        addModule(2);
    }//GEN-LAST:event_mni_SCSIActionPerformed

    private void mni_SASActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mni_SASActionPerformed
        addModule(3);
    }//GEN-LAST:event_mni_SASActionPerformed

    private void mni_floppyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mni_floppyActionPerformed
        addModule(4);
    }//GEN-LAST:event_mni_floppyActionPerformed

    private void tre_DevicesValueChanged(javax.swing.event.TreeSelectionEvent evt) {//GEN-FIRST:event_tre_DevicesValueChanged
        updateButtons();
    }//GEN-LAST:event_tre_DevicesValueChanged

    private void lbl_remModuleMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lbl_remModuleMouseClicked
        if (!lbl_remModule.isEnabled()) {
            return;
        }
        remModule();
    }//GEN-LAST:event_lbl_remModuleMouseClicked

    private void lbl_addDeviceMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lbl_addDeviceMouseClicked
        if (!lbl_addDevice.isEnabled()) {
            return;
        }
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) tre_Devices.getLastSelectedPathComponent();
        Object[] data = (Object[]) node.getUserObject();
        if ((Integer) data[0] == IDE_MODULE) {
            pmn_addDevices.show(lbl_addDevice, evt.getX(), evt.getY());
            return;
        }
        if ((Integer) data[0] == FLOPPY_MODULE) {
            addDevice(FLOPPY_DEVICE, node);
            return;
        }
        addDevice(HDD_DEVICE, node);
    }//GEN-LAST:event_lbl_addDeviceMouseClicked

    private void mni_addDVDActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mni_addDVDActionPerformed
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) tre_Devices.getLastSelectedPathComponent();
        addDevice(DVD_DEVICE, node);
    }//GEN-LAST:event_mni_addDVDActionPerformed

    private void mni_addHDDActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mni_addHDDActionPerformed
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) tre_Devices.getLastSelectedPathComponent();
        addDevice(HDD_DEVICE, node);
    }//GEN-LAST:event_mni_addHDDActionPerformed

    private void lbl_remDeviceMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lbl_remDeviceMouseClicked
        if (!lbl_remDevice.isEnabled()) {
            return;
        }
        remDevice();
    }//GEN-LAST:event_lbl_remDeviceMouseClicked

    private void spn_FeaturesComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_spn_FeaturesComponentResized
        if (panel != null) {
            panel.setBounds(0, 0, spn_Features.getWidth(), spn_Features.getHeight());
        }
    }//GEN-LAST:event_spn_FeaturesComponentResized
// </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Functions">

    public void treeSort(DefaultMutableTreeNode childNode) {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) childNode.getParent();
        TreeNode[] selected = childNode.getPath();
        Enumeration<DefaultMutableTreeNode> children = (Enumeration<DefaultMutableTreeNode>) node.children();
        ArrayList<DefaultMutableTreeNode> childNodes = new ArrayList<DefaultMutableTreeNode>();
        ArrayList<Integer> slots = new ArrayList<Integer>();
        while (children.hasMoreElements()) {
            DefaultMutableTreeNode child = children.nextElement();
            slots.add((Integer) ((HashMap<String, Object>) ((Object[]) child.getUserObject())[2]).get("slot"));
            childNodes.add(child);
        }
        Collections.sort(slots);
        ArrayList<DefaultMutableTreeNode> sortedChildNodes = new ArrayList<DefaultMutableTreeNode>();
        for (Integer slot : slots) {
            for (DefaultMutableTreeNode child : childNodes) {
                if ((Integer) ((HashMap<String, Object>) ((Object[]) child.getUserObject())[2]).get("slot") == slot) {
                    sortedChildNodes.add(child);
                }
            }
        }
        node.removeAllChildren();
        for (DefaultMutableTreeNode child : sortedChildNodes) {
            node.add(child);
        }
        ((DefaultTreeModel) tre_Devices.getModel()).nodeStructureChanged(node);
        tre_Devices.setSelectionPath(new TreePath(selected));
        childNodes.clear();
        childNodes = null;
    }

    public void replaceSlots(int module, boolean[] slots) {
        module_slots[module] = slots;
    }

    private DefaultMutableTreeNode getNewSelectedNode(DefaultMutableTreeNode node) {
        DefaultMutableTreeNode selnode = node.getPreviousSibling();
        if (selnode == null) {
            selnode = node.getNextSibling();
            if (selnode == null) {
                selnode = (DefaultMutableTreeNode) node.getParent();
            }
        }
        return selnode;
    }

    private void checkModuleSelection(DefaultMutableTreeNode node) {
        Object[] data = (Object[]) node.getUserObject();
        boolean state = true;
        switch ((Integer) data[0]) {
            case IDE_MODULE:
                if (node.getChildCount() >= 4) {
                    state = false;
                }
                break;
            case FLOPPY_MODULE:
                if (node.getChildCount() >= 2) {
                    state = false;
                }
                break;
            case SATA_MODULE:
                if (node.getChildCount() >= 30) {
                    state = false;
                }
                break;
            case SCSI_MODULE:
                if (node.getChildCount() >= 16) {
                    state = false;
                }
                break;
            case SAS_MODULE:
                if (node.getChildCount() >= 8) {
                    state = false;
                }
                break;
            default:
                state = false;
        }
        lbl_addDevice.setEnabled(state);
    }

    private void updateButtons() {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) tre_Devices.getLastSelectedPathComponent();
        if (node == null) {
            return;
        }
        Object[] data = (Object[]) node.getUserObject();

        if (!(Boolean) ((HashMap) data[2]).get("isdevice")) {
            if ((Integer) data[0] > -1) {
                lbl_remModule.setEnabled(true);
            } else {
                lbl_remModule.setEnabled(false);
            }
            lbl_remDevice.setEnabled(false);
            checkModuleSelection(node);
        } else {
            lbl_remDevice.setEnabled(true);
            lbl_addDevice.setEnabled(false);
            lbl_remModule.setEnabled(false);
        }
        loadFeatures(node);
    }

    private void loadFeatures(DefaultMutableTreeNode node) {
        Object[] data = (Object[]) node.getUserObject();
        spn_Features.removeAll();
        if((Integer)data[0]==-1){
            spn_Features.updateUI();
            return;
        }
        boolean slots[];
        if (!(Boolean) ((HashMap) data[2]).get("isdevice")) {
            panel = new ModAttributes(node,this);
            panel.setBounds(0, 0, spn_Features.getWidth(), spn_Features.getHeight());
        } else {
            slots = (boolean[]) module_slots[(Integer) data[0]];
            panel = new Attributes(node, slots, this);
            panel.setBounds(0, 0, spn_Features.getWidth(), spn_Features.getHeight());    
        }
        spn_Features.add(panel, null);
        spn_Features.updateUI();
    }

    private void EnableModules(int id, boolean state) {
        switch (id) {
            case IDE_MODULE:
                mni_IDE.setEnabled(state);
                break;
            case SATA_MODULE:
                mni_SATA.setEnabled(state);
                break;
            case SCSI_MODULE:
                mni_SCSI.setEnabled(state);
                break;
            case SAS_MODULE:
                mni_SAS.setEnabled(state);
                break;
            case FLOPPY_MODULE:
                mni_floppy.setEnabled(state);
                break;
        }
    }

    private void remDevice() {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) tre_Devices.getLastSelectedPathComponent();
        DefaultMutableTreeNode selnode = getNewSelectedNode(node);
        delSlot(node);
        model.removeNodeFromParent(node);
        lbl_remDevice.setEnabled(false);
        if (selnode != null) {
            tre_Devices.setSelectionPath(new TreePath(selnode.getPath()));
        }
    }

    private void remModule() {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) tre_Devices.getLastSelectedPathComponent();
        Object[] data = (Object[]) node.getUserObject();
        EnableModules((Integer) data[0], true);
        DefaultMutableTreeNode selnode = getNewSelectedNode(node);
        model.removeNodeFromParent(node);
        lbl_remModule.setEnabled(false);
        if (!lbl_addModule.isEnabled()) {
            lbl_addModule.setEnabled(true);
        }
        total_Mods++;
        tre_Devices.updateUI();
        if (selnode != null) {
            tre_Devices.setSelectionPath(new TreePath(selnode.getPath()));
        }
    }

    private void addModule(int id) {
        DefaultMutableTreeNode node = null;
        Object[] data = new Object[3];
        HashMap<String, Object> map = new HashMap<String, Object>();
        data[0] = id;
        switch (id) {
            case IDE_MODULE:
                data[1] = "IDE Module";
                map.put("type", 1);
                map.put("cache", true);
                break;
            case SATA_MODULE:
                data[1] = "SATA Module";
                map.put("type", 0);
                map.put("cache", false);
                break;
            case SCSI_MODULE:
                data[1] = "SCSI Module";
                map.put("type", 0);
                map.put("cache", false);
                break;
            case SAS_MODULE:
                data[1] = "SAS Controller";
                map.put("type", 0);
                map.put("cache", false);
                break;
            case FLOPPY_MODULE:
                data[1] = "Floppy Module";
                map.put("type", 0);
                map.put("cache", true);
                break;
            default:
                data[1] = "Unknow Module";
                data[0] = -2;
        }
        map.put("isdevice", false);
        data[2] = map;
        node = new DefaultMutableTreeNode(data);
        EnableModules(id, false);
        ((DefaultTreeModel) tre_Devices.getModel()).insertNodeInto(node, (DefaultMutableTreeNode)model.getRoot(), ((DefaultMutableTreeNode) model.getRoot()).getChildCount());
        tre_Devices.updateUI();
        total_Mods--;
        if (total_Mods == 0) {
            lbl_addModule.setEnabled(false);
        }
        tre_Devices.setSelectionPath(new TreePath(node.getPath()));
    }

    public File selectHDD(int device) {
        int action;
        JFileChooser file = new JFileChooser();
        file.resetChoosableFileFilters();
        switch (device) {
            case HDD_DEVICE:
                if (toolbar.data.get(Namespace.keyMaps.HYPERVISOR).toString().equals(Namespace.HiperVisors.VIRTUALPC)) {
                    file.setFileFilter(new ExtensionFilter("Virtual Machine Disk (*.vmdk *.vdi *.vhd *.hdd *.bin)", new String[]{".vmdk", ".vdi", ".vhd", ".hdd", ".bin"}));
                } else {
                    file.addChoosableFileFilter(new ExtensionFilter("Kuasar Disk Image (*.kdi)", ".kdi"));
                    file.addChoosableFileFilter(new ExtensionFilter("Virtual Machine Disk (*.vmdk *.vdi *.vhd *.hdd *.bin)", new String[]{".vmdk", ".vdi", ".vhd", ".hdd", ".bin"}));
                    file.setFileFilter(new ExtensionFilter("All Supported Machine Disks (*.kdi *.vmdk *.vdi *.vhd *.hdd *.bin)", new String[]{".kdi", ".vmdk", ".vdi", ".vhd", ".hdd", ".bin"}));
                }
                break;
            case DVD_DEVICE:
                file.setFileFilter(new ExtensionFilter("CD/DVD-ROM Disk Image (*.iso)", ".iso"));
                break;
            case FLOPPY_DEVICE:
                file.setFileFilter(new ExtensionFilter("Floppy images (*.img)", ".img"));
        }


        file.setDialogTitle("Select a Disk Image");
        file.setFileSelectionMode(JFileChooser.FILES_ONLY);
        file.setMultiSelectionEnabled(false);
        action = file.showOpenDialog(this);
        switch (action) {
            case JFileChooser.APPROVE_OPTION:
                return file.getSelectedFile();
            case JFileChooser.CANCEL_OPTION:
                return null;
            case JFileChooser.ERROR_OPTION:
                System.err.println("Error selecting image disk file");
        }
        return null;
    }

    private void addDevice(int id, DefaultMutableTreeNode node) {
        DefaultMutableTreeNode device;
        Object[] data = new Object[3];
        data[0] = (Integer) ((Object[]) node.getUserObject())[0];
        int slot = getSlot((Integer) data[0]);
        HashMap<String, Object> map = new HashMap<String, Object>();
        File file = null;
        switch (id) {
            case HDD_DEVICE:
                file = selectHDD(id);
                if (file == null) {
                    return;
                }
                map.put("diff", false);
                data[1] = file.getName();
                break;
            case FLOPPY_DEVICE:
                file = null;
                data[1] = "Empty";
                break;
            case DVD_DEVICE:
                file = null;
                data[1] = "Empty";
                map.put("passthrough", false);
                break;
        }
        map.put("slot", slot);
        map.put("file", file);
        map.put("isdevice", true);
        map.put("id", id);
        data[2] = map;
        device = new DefaultMutableTreeNode(data);
        ((DefaultTreeModel) tre_Devices.getModel()).insertNodeInto(device, node, slot);
        tre_Devices.setSelectionPath(new TreePath(node.getPath()));
        tre_Devices.expandPath(new TreePath(node.getPath()));
        tre_Devices.updateUI();
        checkModuleSelection(node);
    }

    private void delSlot(DefaultMutableTreeNode node) {
        if (node == null) {
            return;
        }
        Object[] data = (Object[]) node.getUserObject();
        boolean[] slot = (boolean[]) module_slots[(Integer) data[0]];
        HashMap<String, Object> map = (HashMap<String, Object>) data[2];
        int islot = (Integer) map.get("slot");
        slot[islot] = false;
    }

    private int getSlot(int module) {
        boolean slots[] = (boolean[]) module_slots[module];
        for (int i = 0; i < slots.length; i++) {
            if (!slots[i]) {
                slots[i] = true;
                return i;
            }
        }
        return -1;
    }

    public void setInfo(String text) {
        lbl_Info.setText(text);
        tim_Info.start();
    }

    private long memToMB(int memory, int unit ){
        long total=memory;
        for(int i =0; i<unit; i++){
            total*=1024;
        }
        return total;
    }

    private Object[] MBToMem(long mega){
        Object data[] = new Object[2];
        int unit=0;
        int memory;
        while(mega%1024 == 0 && unit<3){
            mega /= 1024;
            unit++;
        }
        memory= (int)mega;
        data[0]=memory;
        data[1] =unit;
        return data;
    }

    private void Load(){
        if(toolbar.data.get(Namespace.keyMaps.MEMORY)!=null){
            Object data[] = MBToMem((Long) toolbar.data.get(Namespace.keyMaps.MEMORY));
            txt_mem.setText(String.valueOf((Integer)data[0]));
            cmb_unit.setSelectedIndex((Integer)data[1]);
        }
        if(toolbar.data.get(Namespace.keyMaps.SAFEMEMORY)!=null){
            safeMode= (Boolean) toolbar.data.get(Namespace.keyMaps.SAFEMEMORY);
            if(safeMode)
                lbl_SafeMode.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kuasar/plugin/vmcreator/icons/security-high.png")));
        }
        if(toolbar.data.get(Namespace.keyMaps.DEVICES)!=null){
            TreeModel devices = (TreeModel)toolbar.data.get(Namespace.keyMaps.DEVICES);
            tre_Devices.setModel(devices);
            model=(DefaultTreeModel) devices;
            total_Mods = total_Mods-model.getChildCount(model.getRoot());
            for(int i=0; i<model.getChildCount(model.getRoot()); i++){
               EnableModules( (Integer)(((Object[])((DefaultMutableTreeNode) model.getChild(model.getRoot(), i)).getUserObject())[0]),false);
            }
        }
        if(toolbar.data.get(Namespace.keyMaps.DEVICES+".slots")!=null){
            module_slots=(Object[]) toolbar.data.get(Namespace.keyMaps.DEVICES+".slots");
        }
            
    }

    private void save() {
        int memory_size;
        try{
           memory_size = Integer.parseInt(txt_mem.getText());  
        }catch(NumberFormatException e){
            return;
        }
        toolbar.data.put(Namespace.keyMaps.MEMORY, memToMB(memory_size, (Integer)cmb_unit.getSelectedIndex()));
        toolbar.data.put(Namespace.keyMaps.DEVICES, tre_Devices.getModel());
        toolbar.data.put(Namespace.keyMaps.DEVICES + ".slots", module_slots);
        toolbar.data.put(Namespace.keyMaps.SAFEMEMORY, safeMode);
    }

    //</editor-fold>
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btn_Cancel;
    private javax.swing.JButton btn_Next;
    private javax.swing.JButton btn_Previous;
    private javax.swing.JComboBox cmb_unit;
    private javax.swing.JLabel lbl_Disks;
    private javax.swing.JLabel lbl_Info;
    private javax.swing.JLabel lbl_SafeMode;
    private javax.swing.JLabel lbl_addDevice;
    private javax.swing.JLabel lbl_addModule;
    private javax.swing.JLabel lbl_mem;
    private javax.swing.JLabel lbl_remDevice;
    private javax.swing.JLabel lbl_remModule;
    private javax.swing.JMenuItem mni_IDE;
    private javax.swing.JMenuItem mni_SAS;
    private javax.swing.JMenuItem mni_SATA;
    private javax.swing.JMenuItem mni_SCSI;
    private javax.swing.JMenuItem mni_addDVD;
    private javax.swing.JMenuItem mni_addHDD;
    private javax.swing.JMenuItem mni_floppy;
    private javax.swing.JPopupMenu pmn_addDevices;
    private javax.swing.JPopupMenu pmn_addModule;
    private javax.swing.JScrollPane spn_Devices;
    private javax.swing.JScrollPane spn_Features;
    private javax.swing.JTree tre_Devices;
    private javax.swing.JTextField txt_mem;
    // End of variables declaration//GEN-END:variables
}

class ExtensionFilter extends FileFilter {

    private String extensions[];
    private String description;

    public ExtensionFilter(String description, String extension) {
        this(description, new String[]{extension});
    }

    public ExtensionFilter(String description, String extensions[]) {
        this.description = description;
        this.extensions = (String[]) extensions.clone();
    }

    public boolean accept(File file) {
        if (file.isDirectory()) {
            return true;
        }
        int count = extensions.length;
        String path = file.getAbsolutePath();
        for (int i = 0; i < count; i++) {
            String ext = extensions[i];
            if (path.endsWith(ext)
                    && (path.charAt(path.length() - ext.length()) == '.')) {
                return true;
            }
        }
        return false;
    }

    @Override
    public String getDescription() {
        return description;
    }
}
